home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-11-08 | 17.5 KB | 646 lines | [TEXT/MPS ] |
- //========================================================================================
- //
- // File: FWGrUtil.cpp
- // Release Version: $ 1.0d11 $
- //
- // Copyright: © 1993, 1995 by Apple Computer, Inc., all rights reserved.
- //
- //========================================================================================
-
- #include "FWOS.hpp"
-
- #ifndef FWGRUTIL_H
- #include "FWGrUtil.h"
- #endif
-
- #ifndef FWRECT_H
- #include "FWRect.h"
- #endif
-
- #ifndef FWPOINT_H
- #include "FWPoint.h"
- #endif
-
- #ifndef FWFXMATH_H
- #include "FWFxMath.h"
- #endif
-
- #ifndef FWBWPAT_H
- #include "FWBWPat.h"
- #endif
-
- #ifndef FWGCONST_H
- #include "FWGConst.h"
- #endif
-
- #ifndef FWREGION_H
- #include "FWRegion.h"
- #endif
-
- #ifndef FWODGEOM_H
- #include "FWODGeom.h"
- #endif
-
- // ----- Foundation Includes -----
-
- #ifndef FWPRIDEB_H
- #include "FWPriDeb.h"
- #endif
-
- // ----- OpenDoc Includes -----
-
- #ifndef SOM_ODShape_xh
- #include <Shape.xh>
- #endif
-
- #ifndef SOM_ODTransform_xh
- #include <Trnsform.xh>
- #endif
-
- // ----- C Includes -----
-
- #if defined(FW_BUILD_MAC) & !defined(__FP__)
- #include <FP.h>
- #endif
-
- #if defined(FW_BUILD_WIN) & !defined(__MATH_H)
- #include <Math.h>
- #endif
-
- #ifdef FW_DEBUG
- #include <stdio.h> // for sprintf()
- #endif
-
- // ------ Platform includes ------
-
- #if defined(FW_BUILD_MAC) & !defined(__QDOFFSCREEN__)
- #include <QDOffscreen.h>
- #endif
-
- //========================================================================================
- // RunTime Info
- //========================================================================================
-
- #if FW_LIB_EXPORT_PRAGMAS
- #pragma lib_export on
- #endif
-
- #ifdef FW_BUILD_MAC
- #pragma segment FWGraphx_GrUtil
- #endif
-
- //========================================================================================
- // Global Methods
- //========================================================================================
-
- //-------------------------------------------------------------------------
- // FW_CreateLineODShape
- //-------------------------------------------------------------------------
-
- FW_FUNC_ATTR ODShape* FW_CreateLineODShape(Environment *ev, const FW_CPoint& from, const FW_CPoint& to, FW_CFixed penSize)
- {
- FW_CPoint lineThickness(penSize, penSize);
-
- ODShape* shape = ::FW_NewODShape(ev);
- ::FW_SetShapeRegion(ev, shape, ::FW_CreateLineRegion( from, to, lineThickness));
- return shape;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CreateOvalODShape
- //----------------------------------------------------------------------------------------
-
- FW_FUNC_ATTR ODShape* FW_CreateOvalODShape(Environment *ev, const FW_CRect& rect)
- {
- ODShape* shape = ::FW_NewODShape(ev);
- ::FW_SetShapeRegion(ev, shape, ::FW_CreateOvalRegion(rect));
- return shape;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CreateArcODShape
- //----------------------------------------------------------------------------------------
-
- FW_FUNC_ATTR ODShape* FW_CreateArcODShape(Environment *ev, const FW_CRect& rect, short startAngle, short arcAngle)
- {
- ODShape* shape = ::FW_NewODShape(ev);
- ::FW_SetShapeRegion(ev, shape, ::FW_CreateArcRegion(rect, startAngle, arcAngle));
- return shape;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CreateRoundRectODShape
- //----------------------------------------------------------------------------------------
-
- FW_FUNC_ATTR ODShape* FW_CreateRoundRectODShape(Environment *ev, const FW_CRect& rect, const FW_CPoint& ovalSize)
- {
- ODShape* shape = ::FW_NewODShape(ev);
- ::FW_SetShapeRegion(ev, shape, ::FW_CreateRoundRectRegion(rect, ovalSize));
- return shape;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_OutlineODShape
- //----------------------------------------------------------------------------------------
-
- FW_FUNC_ATTR void FW_OutlineODShape(Environment *ev, ODShape* odShapeToOutline, FW_CFixed outlineSize)
- {
- ODShape* odTempShape = ::FW_NewODShape(ev, odShapeToOutline);
-
- if (outlineSize <= FW_kFixed0)
- outlineSize = FW_kFixedPos1;
-
- odTempShape->Outset(ev, -outlineSize.AsODFixed());
-
- odShapeToOutline->Subtract(ev, odTempShape);
- odTempShape->Release(ev);
- }
-
- #ifdef FW_BUILD_MAC
- //----------------------------------------------------------------------------------------
- // FW_MacPrivGetPortTextStyle
- //----------------------------------------------------------------------------------------
-
- void FW_MacPrivGetPortTextStyle(TextStyle& theTextStyle)
- {
- GrafPtr curPort = FW_QDGlobals.thePort;
- theTextStyle.tsFont = curPort->txFont;
- theTextStyle.tsFace = curPort->txFace;
- theTextStyle.tsSize = curPort->txSize;
- }
- #endif
-
- #ifdef FW_BUILD_MAC
- //----------------------------------------------------------------------------------------
- // FW_MacPrivSetPortTextStyle
- //----------------------------------------------------------------------------------------
-
- void FW_MacPrivSetPortTextStyle(const TextStyle& theTextStyle)
- {
- ::TextFont(theTextStyle.tsFont);
- ::TextFace(theTextStyle.tsFace);
- ::TextSize(theTextStyle.tsSize);
- }
- #endif
-
- #ifdef FW_BUILD_MAC
- //----------------------------------------------------------------------------------------
- // FW_MacIsColorPort
- //----------------------------------------------------------------------------------------
-
- FW_Boolean FW_MacIsColorPort(GrafPtr grafPort)
- {
- return ((CGrafPtr)grafPort)->portVersion < 0;
- }
- #endif
-
- #ifdef FW_BUILD_MAC
- //========================================================================================
- // class FW_CMacTempPort
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // FW_CMacTempPort::FW_CMacTempPort
- //----------------------------------------------------------------------------------------
-
- FW_CMacTempPort::FW_CMacTempPort(GrafPtr tempPort /* = NULL */)
- {
- ::GetPort(&fMacPort);
-
- if (tempPort != NULL)
- SetPort(tempPort);
-
- FW_END_CONSTRUCTOR
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CMacTempPort::~FW_CMacTempPort
- //----------------------------------------------------------------------------------------
-
- FW_CMacTempPort::~FW_CMacTempPort()
- {
- FW_START_DESTRUCTOR
-
- ::SetPort(fMacPort);
- }
-
- #endif
-
- #ifdef FW_BUILD_WIN
-
- //----------------------------------------------------------------------------------------
- // FW_WinPrivGetDisplayColorInfo
- //----------------------------------------------------------------------------------------
-
- FW_FUNC_ATTR void FW_WinPrivGetDisplayColorInfo(short& planeCount, short& bitsPixel)
- {
- static short gPlaneCount = -1;
- static short gBitsPixel = -1;
-
- if(gPlaneCount == -1)
- {
- HDC hDC = ::GetDC(NULL);
- gPlaneCount = (short) ::GetDeviceCaps(hDC, PLANES);
- gBitsPixel = (short) ::GetDeviceCaps(hDC, BITSPIXEL);
- ::ReleaseDC(NULL, hDC);
- }
-
- planeCount = gPlaneCount;
- bitsPixel = gBitsPixel;
- }
-
- #endif
-
- //----------------------------------------------------------------------------------------
- // FW_PtInOval
- //----------------------------------------------------------------------------------------
-
- FW_FUNC_ATTR FW_Boolean FW_PtInOval(const FW_CRect& ovalRect, const FW_CPoint& test)
- {
- // A brief refresher in fifth-grade geometry:
-
- // An ellipse (not an oval!) is defined as a set of points such as:
- // (x - x0/a)^2 + (y - y0/b)^2 <= 1, where:
- // <x0, y0> is the center of the ellipse
- // a is the x-radius and b is the y-radius
-
- // It is possible to get rid of division by evaluating
- // (bx)^2 + (ay)^2 <= a^2 * b^2, but this can overflow real easy
-
- if(ovalRect.Contains(test))
- {
- // Adjust center by 0.5 because of how rounding works
- FW_CFixed xMiddle = (ovalRect.left + ovalRect.right - FW_kFixedPos1).Half();
- FW_CFixed yMiddle = (ovalRect.top + ovalRect.bottom - FW_kFixedPos1).Half();
-
- FW_CFixed a = (ovalRect.right - ovalRect.left).Half();
- FW_CFixed b = (ovalRect.bottom - ovalRect.top).Half();
-
- FW_CFixed xa = (test.x - xMiddle) / a;
- xa *= xa;
-
- FW_CFixed xb = (test.y - yMiddle) / b;
- xb *= xb;
-
- return xa + xb <= FW_IntToFixed(1);
- }
-
- return FALSE;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_PtInRoundRect
- //----------------------------------------------------------------------------------------
-
- FW_FUNC_ATTR FW_Boolean FW_PtInRoundRect(const FW_CRect& rect, const FW_CPoint& ovalSize, const FW_CPoint& test)
- {
- if(rect.Contains(test))
- {
- // Find out if the test point may be inside of one of four corner ovals
-
- FW_CRect rectOval;
-
- if(test.x < rect.left + ovalSize.x.Half())
- {
- // Top-left and bottom-left ovals
- rectOval.left = rect.left;
- rectOval.right = rect.left + ovalSize.x;
- }
- else if(test.x > rect.right - ovalSize.x.Half())
- {
- // Top-right and bottom-right ovals
- rectOval.left = rect.right - ovalSize.x;
- rectOval.right = rect.right;
- }
-
- if(test.y < rect.top + ovalSize.y.Half())
- {
- // Top-left and top-right
- rectOval.top = rect.top;
- rectOval.bottom = rect.top + ovalSize.y;
- }
- else if(test.y > rect.bottom - ovalSize.y.Half())
- {
- // Bottom-left and bottom-right ovals
- rectOval.top = rect.bottom - ovalSize.y;
- rectOval.bottom = rect.bottom;
- }
-
- if(rectOval.IsEmpty())
- return TRUE;
-
- return ::FW_PtInOval(rectOval, test);
- }
-
- return FALSE;
- }
-
- //----------------------------------------------------------------------------------------
- // RegionCode
- //----------------------------------------------------------------------------------------
-
- static short RegionCode(const FW_CPoint& line, const FW_CRect& rect)
- {
- short regionCode = 0;
- if (line.x < rect.left)
- regionCode = 0x0008;
- else if (line.x > rect.right)
- regionCode = 0x0004;
-
- if (line.y < rect.top)
- regionCode |= 0x0001;
- else if (line.y > rect.bottom)
- regionCode |= 0x0002;
-
- return regionCode;
- }
-
- //----------------------------------------------------------------------------------------
- // ::FW_HitTestLine
- //----------------------------------------------------------------------------------------
- // Uses a modified Cohen-Suterland with midpoint subdivision. Here we don't try to clip but
- // just to find if a line intersect a rectangle of size 2*tolerance
-
- FW_FUNC_ATTR FW_Boolean FW_HitTestLine(const FW_CPoint& pt1, const FW_CPoint& pt2,
- const FW_CPoint& test, FW_CFixed tolerance)
- {
- FW_CRect rect(test.x - tolerance,
- test.y - tolerance,
- test.x + tolerance,
- test.y + tolerance);
-
- short regionCode1, regionCode2, middleCode;
-
- if ((regionCode1 = RegionCode(pt1, rect)) == 0)
- return TRUE; // start is inside the rectangle
-
- if ((regionCode2 = RegionCode(pt2, rect)) == 0)
- return TRUE; // end is inside the rectangle
-
- if ((regionCode1 & regionCode2) != 0)
- return FALSE; // line totally outside
-
- FW_CPoint h1(pt1), h2(pt2);
- FW_CPoint middle((h1.x + h2.x).Half(), (h1.y + h2.y).Half());
-
- while (middle != h1 || middle != h2)
- {
- if ((middleCode = RegionCode(middle, rect)) == 0)
- return TRUE; // middle is in the rectangle
-
- if ((middleCode & regionCode1) != 0)
- {
- // line (middle, h1) outside the rectangle
- h1 = middle;
- regionCode1 = middleCode;
- }
- else
- {
- // line (h2, middle) outside the rectangle
- h2 = middle;
- regionCode2 = middleCode;
- }
-
- if ((regionCode1 & regionCode2) != 0)
- return FALSE; // line (h1, h2) totally outside
-
- middle.Set((h1.x + h2.x).Half(), (h1.y + h2.y).Half());
- }
-
- return FALSE;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_PrivCalcArcPoints
- //----------------------------------------------------------------------------------------
- // [KVV] Need to be changed. Could do better than that.
-
- void FW_PrivCalcArcPoints(const FW_SPlatformRect& rect,
- short angle,
- FW_SPlatformPoint& arcPoint)
- {
- if (angle >= 360)
- angle = angle % 360;
- else if(angle < 0)
- angle = (angle % 360) + 360;
-
- FW_PlatformCoordinate middleX = (rect.right + rect.left) / 2;
- FW_PlatformCoordinate middleY = (rect.right + rect.left) / 2;
- const FW_CFixed halfX = FW_IntToFixed((rect.right - rect.left) / 2);
- const FW_CFixed halfY = FW_IntToFixed((rect.bottom - rect.top) / 2);
-
- switch (angle)
- {
- case 0:
- arcPoint.Set(middleX, rect.top);
- break;
- case 45:
- arcPoint.Set(rect.right, rect.top);
- break;
- case 90:
- arcPoint.Set(rect.right, middleY);
- break;
- case 135:
- arcPoint.Set(rect.right, rect.bottom);
- break;
- case 180:
- arcPoint.Set(middleX, rect.bottom);
- break;
- case 225:
- arcPoint.Set(rect.left, rect.bottom);
- break;
- case 270:
- arcPoint.Set(rect.left, middleY);
- break;
- case 315:
- arcPoint.Set(rect.left, rect.top);
- break;
-
- default:
- FW_CFixed fxRad = (FW_IntToFixed(90 - angle) * FW_kFixedPI) / FW_IntToFixed(180);
- if (angle < 45)
- arcPoint.Set((halfX * fxRad.Cos()).AsInt() + middleX, rect.top);
- else if (angle > 45 && angle < 135)
- arcPoint.Set(rect.right, (halfY * fxRad.Sin()).AsInt() + middleY);
- else if (angle < 180)
- arcPoint.Set((halfX * fxRad.Cos()).AsInt() + middleX, rect.bottom);
- else
- {
- fxRad = (FW_IntToFixed(angle - 270) * FW_kFixedPI) / FW_IntToFixed(180);
- if (angle < 45)
- arcPoint.Set(middleX - (halfX * fxRad.Cos()).AsInt(), rect.top);
- else if (angle > 45 && angle < 135)
- arcPoint.Set(rect.right, middleY - (halfY * fxRad.Sin()).AsInt());
- else if (angle < 180)
- arcPoint.Set(middleX - (halfX * fxRad.Cos()).AsInt(), rect.bottom);
- }
- break;
- }
- }
-
- //----------------------------------------------------------------------------------------
- // ::Priv_FormatPoint
- //----------------------------------------------------------------------------------------
-
- static void Priv_FormatPoint(char *s, const char* prompt, const FW_CPoint& point)
- {
- #ifdef FW_DEBUG
- sprintf(s, "%s X: %f Y: %f", prompt, point.x.AsDouble(), point.y.AsDouble());
- #endif
- }
-
- //----------------------------------------------------------------------------------------
- // ::Priv_FormatRect
- //----------------------------------------------------------------------------------------
-
- static void Priv_FormatRect(char *s, const char* prompt, const FW_CRect& rect)
- {
- #ifdef FW_DEBUG
- sprintf(s, "%s left: %f top: %f right: %f bottom: %f",
- prompt,
- rect.left.AsDouble(),
- rect.top.AsDouble(),
- rect.right.AsDouble(),
- rect.bottom.AsDouble());
- #endif
- }
-
- //----------------------------------------------------------------------------------------
- // ::FW_LogPoint
- //----------------------------------------------------------------------------------------
-
- FW_FUNC_ATTR void FW_LogPoint(Environment* ev, const char* prompt, const FW_CPoint& point)
- {
- #ifdef FW_DEBUG
- char s[255];
- Priv_FormatPoint(s, prompt, point);
- FW_CDebugConsole::LogMessage(s);
- #endif
- }
-
- //----------------------------------------------------------------------------------------
- // ::FW_LogRect
- //----------------------------------------------------------------------------------------
-
- FW_FUNC_ATTR void FW_LogRect(Environment* ev, const char* prompt, const FW_CRect& rect)
- {
- #ifdef FW_DEBUG
- char s[255];
- Priv_FormatRect(s, prompt, rect);
- FW_CDebugConsole::LogMessage(s);
- #endif
- }
-
- //----------------------------------------------------------------------------------------
- // ::FW_LogShape
- //----------------------------------------------------------------------------------------
-
- FW_FUNC_ATTR void FW_LogShape(Environment* ev, const char* prompt, ODShape* shape)
- {
- #ifdef FW_DEBUG
- char s[255];
- FW_CRect rect;
- shape->GetBoundingBox(ev, (ODRect*) &rect);
- FW_LogRect(ev, prompt, rect);
- #endif
- }
-
- //----------------------------------------------------------------------------------------
- // ::FW_LogTransform
- //----------------------------------------------------------------------------------------
-
- FW_FUNC_ATTR void FW_LogTransform(Environment* ev, const char* prompt, ODTransform* transform)
- {
- #ifdef FW_DEBUG
- FW_CPoint ptScale;
- transform->GetScale(ev, (ODPoint*) &ptScale);
-
- FW_CPoint ptOffset;
- transform->GetOffset(ev, (ODPoint*) &ptOffset);
-
- char s[128];
- ::sprintf(s,
- "xform: %s: pt * [%.2f, %.2f] + [%.2f, %.2f]\n",
- prompt,
- ptScale.x.AsDouble(), ptScale.y.AsDouble(),
- ptOffset.x.AsDouble(), ptOffset.y.AsDouble());
-
- FW_CDebugConsole::LogMessage(s);
- #endif
- }
-
- #ifdef FW_BUILD_MAC
-
- //----------------------------------------------------------------------------------------
- // ::FW_MacShowColorTable
- //----------------------------------------------------------------------------------------
-
- FW_FUNC_ATTR void FW_MacShowColorTable(CTabHandle cth)
- {
- #ifdef FW_DEBUG
- if (cth == NULL)
- return;
-
- short nColors = (*cth)->ctSize + 1;
-
- short cellSize;
- short xCount, yCount;
-
- if (nColors == 256)
- {
- cellSize = 30;
- xCount = 16;
- yCount = 16;
- }
- else
- {
- cellSize = 50;
- xCount = 4;
- yCount = nColors / xCount;
- }
-
- GDHandle gd = ::GetMainDevice();
- if ((*gd)->gdNextGD != NULL)
- gd = (GDHandle) (*gd)->gdNextGD;
-
- PixMapHandle pmh = (*gd)->gdPMap;
-
- Rect rect;
- rect.left = (*pmh)->bounds.left + 50;
- rect.top = (*pmh)->bounds.top + 50;
- rect.right = rect.left + cellSize * xCount;
- rect.bottom = rect.top + cellSize * yCount;
-
- WindowPtr window = ::NewCWindow(NULL, &rect, "\pColor table", TRUE,
- noGrowDocProc, (WindowPtr) -1L, FALSE, 0);
-
- if (window != NULL)
- {
- FW_CMacTempPort port = window;
-
- short nCurColor = 0;
- for (short xColor = 0; xColor < xCount; ++ xColor)
- {
- for (short yColor = 0; yColor < yCount; ++ yColor)
- {
- ::RGBBackColor(&(*cth)->ctTable[nCurColor].rgb);
-
- Rect cell;
- cell.left = xColor * cellSize;
- cell.top = yColor * cellSize;
- cell.right = cell.left + cellSize;
- cell.bottom = cell.top + cellSize;
- ::EraseRect(&cell);
-
- ++ nCurColor;
- }
- }
- }
-
- if (window != NULL)
- ::DisposeWindow(window);
- #endif
- }
-
- #endif
-